﻿using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using AutoMapper;

namespace System.Repository.Base
{
    /// <summary>
    /// 自动赋值
    /// </summary>
    public class AutoSetValue
    {
        //public static TArget AutoCopy<TArget, TCurrent>(TCurrent parent)
        //    where TArget : class, new()
        //    where TCurrent : class, new()
        //{
        //    return ExpressionGenericMapper<TCurrent, TArget>.Trans(parent);
        //}

        ///// <summary>
        ///// 不同类 相同属性 进行赋值
        ///// </summary> 
        ///// <typeparam name="TArget">目标类</typeparam>
        ///// <typeparam name="TCurrent">当前类</typeparam>
        //public static TArget AutoCopy<TArget, TCurrent>(TArget target, TCurrent parent)
        //    where TArget : class, new()
        //    where TCurrent : class, new()
        //{
        //    if (parent != null)
        //    {
        //        if (target == null)
        //            target = new TArget();
        //        var config = new MapperConfiguration(cfg => cfg.CreateMap<TCurrent, TArget>());
        //        var mapper = config.CreateMapper();
        //        target = mapper.Map<TArget>(parent);
        //        return target;
        //    }

        //    return default(TArget);
        //}

        /// <summary>
        /// 不同类 相同属性 进行赋值
        /// </summary> 
        /// <typeparam name="TArget">目标类</typeparam>
        /// <typeparam name="TCurrent">当前类</typeparam>
        public static TArget AutoCopy<TArget, TCurrent>(TArget target, TCurrent parent)
        where TArget : class, new()
        where TCurrent : class, new()
        {
            if (parent != null)
            {
                if (target == null)
                    target = new TArget();
                var parentType = typeof(TCurrent);
                //当前实体 属性
                var properties = parentType.GetProperties();
                //目标类型
                Type type = target.GetType();
                //循环遍历 当前实体 属性
                foreach (var propertie in properties)
                {
                    if (propertie.CanRead)
                    {
                        PropertyInfo targetpropertie = type.GetProperty(propertie.Name); //获取 目标属性
                        //当前是否可读
                        if (targetpropertie != null)
                        {
                            //目标是否可写
                            if (targetpropertie.CanWrite)
                            {
                                //当前类型 ? 目标类型
                                if (targetpropertie.PropertyType.FullName != null &&
                                    targetpropertie.PropertyType.FullName.Equals(propertie.PropertyType.FullName))
                                {
                                    //当前 是否为null
                                    if (propertie.GetValue(parent, null) != null)
                                    {
                                        //当前 !=目标
                                        if (!propertie.GetValue(parent, null)
                                            .Equals(targetpropertie.GetValue(target, null)))
                                        {
                                            //进行属性拷贝

                                            targetpropertie.SetValue(target, propertie.GetValue(parent, null), null);
                                        }
                                    }
                                    else
                                    {
                                        ////当前实体为null处理
                                        //if (targetpropertie.GetValue(target, null) != null)
                                        //{//目标实体为null
                                        //    targetpropertie.SetValue(target, null, null);
                                        //}
                                    }
                                }
                            }
                        }
                    }
                }

                return target;
            }

            return null;
            //}
        }
    }


    /// <summary>
    /// 生成表达式目录树  泛型缓存
    /// </summary>
    /// <typeparam name="TIn"></typeparam>
    /// <typeparam name="TOut"></typeparam>
    public class ExpressionGenericMapper<TIn, TOut>
    {
        private static Func<TIn, TOut> _FUNC = null;
        static ExpressionGenericMapper()
        {
            ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p");
            List<MemberBinding> memberBindingList = new List<MemberBinding>();
            foreach (var item in typeof(TOut).GetProperties())
            {
                MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name));
                MemberBinding memberBinding = Expression.Bind(item, property);
                memberBindingList.Add(memberBinding);
            }
            foreach (var item in typeof(TOut).GetFields())
            {
                MemberExpression property = Expression.Field(parameterExpression, typeof(TIn).GetField(item.Name));
                MemberBinding memberBinding = Expression.Bind(item, property);
                memberBindingList.Add(memberBinding);
            }
            MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray());
            Expression<Func<TIn, TOut>> lambda = Expression.Lambda<Func<TIn, TOut>>(memberInitExpression, new ParameterExpression[]
            {
                    parameterExpression
            });
            _FUNC = lambda.Compile();//拼装是一次性的
        }
        public static TOut Trans(TIn t)
        {
            return _FUNC(t);
        }
    }
}
